﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Text.RegularExpressions;

namespace CRM.Tools.JavaScriptConverter
{
    /// <summary>
    /// Helper functions for processing conversion of script
    /// </summary>
    public static class ConversionHelper
    {

        /// <summary>
        /// Open xml file
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static XmlDocument OpenConversionList(String file)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(file);
            return doc;

        } // OpenConversionList

        /// <summary>
        /// Convert the specified script using the supplied conversion items (snippets)
        /// </summary>
        /// <param name="CRM4Script"></param>
        /// <param name="ConversionItems"></param>
        /// <returns>Converted CRM 2011 script</returns>
        public static String ConvertScript(String CRM4Script, XmlNodeList ConversionItems)
        {
            String regExSeperator = @"\|_\|";   // Used for reguler expression string splitting
            String seperator = "|_|";           // Used for standard string detection

            // Iterate through conversion items and locate occurrences in the supplied script text
            foreach (XmlNode item in ConversionItems)
            {
                // Only process if the conversion item (snippet) has a crm4 node value
                if (!String.IsNullOrEmpty(item.SelectSingleNode("crm4").InnerText) && !String.IsNullOrEmpty(item.SelectSingleNode("crm5").InnerText))
                {
                    // Determine if the conversion item (snippet) has a variable section e.g. |_|
                    if (item.SelectSingleNode("crm4").InnerText.Contains(seperator))
                    {
                        //
                        // As the conversion item (snippet) does have a variable section e.g. |_| we need to perform further actions
                        //

                        // Break down the conversion item (snippet) into an array
                        String[] crm4Text = Regex.Split(item.SelectSingleNode("crm4").InnerText, regExSeperator);
                        String[] crm5Text = Regex.Split(item.SelectSingleNode("crm5").InnerText, regExSeperator);

                        // Get offset in script of the first occurrence
                        int itemOffset = CRM4Script.IndexOf(crm4Text[0]);

                        // Iterate through script to find all occurrences
                        while (itemOffset != -1)
                        {
                            String codeSnippet = "";

                            // Determine the end of the occurrence to process. (e.g. Firstly Look for a space (if a space is not in the snippet) Then ;  Then a line break)
                            int firstSpace = item.SelectSingleNode("crm4").InnerText.Contains(" ") ? 0 : CRM4Script.IndexOf(' ', itemOffset);
                            int firstSemiColon = CRM4Script.IndexOf(';', itemOffset);
                            int firstLineBreak = CRM4Script.IndexOf('\n', itemOffset);
                            int codeSnippetEnd = firstSpace;
                            if ((firstSemiColon != -1 && codeSnippetEnd > firstSemiColon) || (codeSnippetEnd == 0 | codeSnippetEnd == -1))
                            {
                                codeSnippetEnd = firstSemiColon;
                                if (item.SelectSingleNode("crm4").InnerText.EndsWith(";"))
                                    codeSnippetEnd += 1;
                            }
                            if (firstLineBreak != -1 && codeSnippetEnd > firstLineBreak)
                                codeSnippetEnd = firstLineBreak;

                            // Get the end of the CRM 4 occurrence 
                            int occurenceEnd = CRM4Script.IndexOf(crm4Text[crm4Text.Length - 1], itemOffset ) ;

                            if (occurenceEnd > -1 && occurenceEnd <= codeSnippetEnd)
                            {
                                occurenceEnd += crm4Text[crm4Text.Length - 1].Length;
                                // Get the line of code to process
                                codeSnippet = CRM4Script.Substring(itemOffset, occurenceEnd - itemOffset);

                                String newCodesnippet = ""; // Holds the new CRM 2011 code snippet
                                int offsetTmp = 0;          // Holds the offset value when processing more then one variable in the code snippet
                                int stripRightHandCharacterTotalTmp = 0;

                                // Iterate through the CRM4 code snippet and process each variable section e.g. |_| , this is determined by the size of the crm4Text snippet array
                                for (int variableInstance = 1; variableInstance < crm4Text.Length; variableInstance++)
                                {
                                    // Retrieve offset of next section from the code snippet that matches the following conversion items.
                                    int nextSection = codeSnippet.IndexOf(crm4Text[variableInstance]);

                                    // Check if the next section matches the script we are trying to find.
                                    if (nextSection != -1)
                                    {
                                        int stripRightHandCharacterTotal = 0; // Handles variables such as |_|2 which removes 2 characters from the variable text (e.g. myField_c -> myField)
                                        Int32.TryParse(crm5Text[variableInstance][0].ToString(), out stripRightHandCharacterTotal); // Determine if special string manipulation needs to occur

                                        // Retrieve the variable string from the CRM4 code snippet
                                        String variableString = codeSnippet.Substring(crm4Text[variableInstance - 1].Length + offsetTmp, nextSection - crm4Text[variableInstance - 1].Length - offsetTmp - stripRightHandCharacterTotal);
                                        offsetTmp += crm4Text[variableInstance - 1].Length + variableString.Length + stripRightHandCharacterTotal; // Store offset in code snippet for if we need to process a another variable in the code snippet

                                        // Build new CRM 2011 code snippet
                                        if (stripRightHandCharacterTotalTmp == 0)
                                            newCodesnippet += crm5Text[variableInstance - 1] + variableString;
                                        else
                                        {
                                            newCodesnippet += crm5Text[variableInstance - 1].Substring(1) + variableString;
                                            stripRightHandCharacterTotalTmp = 0;
                                        }

                                        // Attach final CRM 2011 section and update script if we do not need to process any more variable sections
                                        if (variableInstance == crm4Text.Length - 1)
                                        {
                                            if (stripRightHandCharacterTotal == 0)
                                                newCodesnippet += crm5Text[crm4Text.Length - 1];
                                            else
                                                newCodesnippet += crm5Text[crm4Text.Length - 1].Substring(1);

                                            // Update the script
                                            CRM4Script = CRM4Script.Replace(codeSnippet, newCodesnippet);
                                            break;
                                        }

                                        if (stripRightHandCharacterTotal != 0)
                                            stripRightHandCharacterTotalTmp = 1;
                                    }
                                    else
                                        break; // Break loop if next section does not match what we are looking for

                                } //for
                            }

                            // Get offset in script of the next occurrence
                            itemOffset = CRM4Script.IndexOf(crm4Text[0], itemOffset + crm4Text[0].Length);

                        } // while
                    }
                    else
                    {
                        //
                        // As the conversion item (snippet) does not have a variable section e.g. |_| simply replace the text
                        //
                        int itemOffset = CRM4Script.IndexOf(item.SelectSingleNode("crm4").InnerText);
                        if (itemOffset > -1)
                            CRM4Script = CRM4Script.Replace(item.SelectSingleNode("crm4").InnerText, item.SelectSingleNode("crm5").InnerText);
                    } // if
                } // if
            } // foreach

            return CRM4Script;
        } // ConvertScript



    }
}
